using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using ZoneFiveSoftware.Common.Data.Fitness;

namespace FilteredStatistics.Data
{
    abstract class IPostProcessFilter : IPluginSerializable, IComparable<IPostProcessFilter>
    {
        public enum PostProcessType
        {
            MergeNearDistances = 0,
            MergeNearTimes,
            RemoveSmallDistances,
            RemoveSmallTimes,
            RemoveAscentRange,
            RemoveDescentRange,
            PostProcessTypeCount,
        };

        public abstract PostProcessType Type { get; }
        public abstract String DisplayString { get; }
        public abstract List<ActivityRangeInfoCache> FilterResults(IList<ActivityRangeInfoCache> wrappersToFilter, IActivity activity);
        public abstract int CompareTo(IPostProcessFilter other);

        public IPostProcessFilter Clone()
        {
            MemoryStream tempStream = new MemoryStream();

            Serialize(tempStream);
            tempStream.Seek(0, SeekOrigin.Begin);

            SerializableInt32Range typeData = new SerializableInt32Range(0);
            IPostProcessFilter.PostProcessType type;
            IPostProcessFilter filter = null;

            typeData.Deserialize(tempStream, Constants.CurrentVersion);
            type = (IPostProcessFilter.PostProcessType)(int)typeData;

            switch (type)
            {
                case IPostProcessFilter.PostProcessType.MergeNearDistances:
                    {
                        filter = new MergeNearDistancesPostProcessFilter(tempStream, Constants.CurrentVersion);
                        break;
                    }
                case IPostProcessFilter.PostProcessType.MergeNearTimes:
                    {
                        filter = new MergeNearTimesPostProcessFilter(tempStream, Constants.CurrentVersion);
                        break;
                    }
                case IPostProcessFilter.PostProcessType.RemoveSmallDistances:
                    {
                        filter = new RemoveSmallDistancesPostProcessFilter(tempStream, Constants.CurrentVersion);
                        break;
                    }
                case IPostProcessFilter.PostProcessType.RemoveSmallTimes:
                    {
                        filter = new RemoveSmallTimesPostProcessFilter(tempStream, Constants.CurrentVersion);
                        break;
                    }
                case IPostProcessFilter.PostProcessType.RemoveAscentRange:
                    {
                        filter = new RemoveAscentRangeSectionsPostProcessFilter(tempStream, Constants.CurrentVersion);
                        break;
                    }
                case IPostProcessFilter.PostProcessType.RemoveDescentRange:
                    {
                        filter = new RemoveDescentRangeSectionsPostProcessFilter(tempStream, Constants.CurrentVersion);
                        break;
                    }
                default:
                    {
                        Debug.Assert(false);
                        break;
                    }
            }

            Debug.Assert(filter != null);

            tempStream.Close();

            return filter;
        }

        public override void Serialize(Stream stream)
        {
            SerializableInt32Range type = new SerializableInt32Range((UInt16)Type);

            type.Serialize(stream);
        }

        public abstract void Deserialize_V2(Stream stream, DataVersion version);
    }
}
